﻿//-----------------------------------------------------------------------
// <copyright>
// This file is subject to the terms and conditions of the Microsoft Public License (MS-PL).
// See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL for more details.
// </copyright>
//----------------------------------------------------------------------- 
using System;
using System.Collections.Generic;
using System.Windows.Threading;
using Fulcrum.DispatcherProxies;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Fulcrum.UnitTests.DispatcherProxies
{
    [TestClass]
    public class ReflectionHelpTests
    {
        public ReflectionHelpTests()
        {
            // nothing
        }

        [TestMethod]
        public void TestReflectionHelpFindObsoleteAttributeNotObsolete()
        {
            var type = typeof(Base);
            var member = type.GetMethod("BaseMethod");
            var attribute = ReflectionHelp.FindObsoleteAttribute(member);

            Assert.IsNull(attribute);
        }

        [TestMethod]
        public void TestReflectionHelpFindObsoleteAttributeObsolete()
        {
            var type = typeof(Derived);
            var member = type.GetMethod("DerivedObsoleteMethod");
            var attribute = ReflectionHelp.FindObsoleteAttribute(member);

            Assert.IsNotNull(attribute);
            Assert.AreEqual("My obsolete", attribute.Message);
        }

        [TestMethod]
        public void TestReflectionHelpFindObsoleteAttributeBaseObsolete()
        {
            var type = typeof(Derived);
            var member = type.GetMethod("VirtualOverridenMethod");
            var attribute = ReflectionHelp.FindObsoleteAttribute(member);

            Assert.IsNull(attribute);
        }

        [TestMethod]
        public void TestReflectionHelpGetParameterTypesNoParameters()
        {
            var type = typeof(Base);
            var member = type.GetMethod("NoParameterMethod");
            var results = ReflectionHelp.GetParameterTypes(member);

            Assert.AreEqual(0, results.Length);
        }

        [TestMethod]
        public void TestReflectionHelpGetParameterTypesOneParameters()
        {
            var type = typeof(Base);
            var member = type.GetMethod("OneParameterMethod");
            var results = ReflectionHelp.GetParameterTypes(member);

            Assert.AreEqual(1, results.Length);
            Assert.AreEqual(typeof(int), results[0]);
        }

        [TestMethod]
        public void TestReflectionHelpGetParameterTypesManyParameters()
        {
            var type = typeof(Base);
            var member = type.GetMethod("ManyParameterMethod");
            var results = ReflectionHelp.GetParameterTypes(member);

            Assert.AreEqual(3, results.Length);
            Assert.AreEqual(typeof(int), results[0]);
            Assert.AreEqual(typeof(string), results[1]);
            Assert.AreEqual(typeof(ICollection<KeyValuePair<bool,long>>), results[2]);
        }

        [TestMethod]
        public void TestReflectionHelpIsMethodInAnyBaseTypeBase()
        {
            var type = typeof(Base);
            var member = type.GetMethod("BaseMethod");
            var results = ReflectionHelp.IsMethodInAnyBaseType(member);

            Assert.IsFalse(results);
        }

        [TestMethod]
        public void TestReflectionHelpIsMethodInAnyBaseTypeMethodNotInBase()
        {
            var type = typeof(Derived);
            var member = type.GetMethod("DerivedObsoleteMethod");
            var results = ReflectionHelp.IsMethodInAnyBaseType(member);

            Assert.IsFalse(results);
        }

        [TestMethod]
        public void TestReflectionHelpIsMethodInAnyBaseTypeMethodInBase()
        {
            var type = typeof(Derived);
            var member = type.GetMethod("VirtualOverridenMethod");
            var results = ReflectionHelp.IsMethodInAnyBaseType(member);

            Assert.IsTrue(results);
        }

        [TestMethod]
        public void TestReflectionHelpIsMethodInAnyBaseTypeConstructorNotInBase()
        {
            var type = typeof(Derived);
            var parameters = new Type[] { typeof(bool) };
            var member = type.GetConstructor(parameters);
            var results = ReflectionHelp.IsMethodInAnyBaseType(member);

            Assert.IsFalse(results);
        }

        [TestMethod]
        public void TestReflectionHelpIsMethodInAnyBaseTypeConstructorInBase()
        {
            var type = typeof(Derived);
            var parameters = new Type[0];
            var member = type.GetConstructor(parameters);
            var results = ReflectionHelp.IsMethodInAnyBaseType(member);

            Assert.IsTrue(results);
        }

        [TestMethod]
        public void TestReflectionHelpIsMethodInAnyBaseTypeOverloadMethodNotInBase()
        {
            var type = typeof(Derived);
            var parameters = new Type[] { typeof(bool), typeof(int) };
            var member = type.GetMethod("OverloadMethod", parameters);
            var results = ReflectionHelp.IsMethodInAnyBaseType(member);

            Assert.IsFalse(results);
        }

        [TestMethod]
        public void TestReflectionHelpIsMethodInAnyBaseTypeOverloadMethodInBase()
        {
            var type = typeof(Derived);
            var parameters = new Type[] { typeof(bool), typeof(string) };
            var member = type.GetMethod("OverloadMethod", parameters);
            var results = ReflectionHelp.IsMethodInAnyBaseType(member);

            Assert.IsTrue(results);
        }


        [TestMethod]
        public void TestReflectionHelpIsMethodInAnyBaseTypeOverloadMethodInDoubleBase()
        {
            var type = typeof(DoubleDerived);
            var parameters = new Type[] { typeof(bool), typeof(string), typeof(int) };
            var member = type.GetMethod("OverloadMethod", parameters);
            var results = ReflectionHelp.IsMethodInAnyBaseType(member);

            Assert.IsTrue(results);
        }

        [TestMethod]
        public void TestReflectionHelpIsOverrideMethodEquals()
        {
            var type = typeof(Derived);
            var method = type.GetMethod("Equals");
            bool result = ReflectionHelp.IsOverrideMethod(method);

            Assert.IsTrue(result);
        }

        [TestMethod]
        public void TestReflectionHelpIsOverrideMethodGetHashCode()
        {
            var type = typeof(Derived);
            var method = type.GetMethod("GetHashCode");
            bool result = ReflectionHelp.IsOverrideMethod(method);

            Assert.IsTrue(result);
        }

        [TestMethod]
        public void TestReflectionHelpIsOverrideMethodToString()
        {
            var type = typeof(Derived);
            var method = type.GetMethod("ToString");
            bool result = ReflectionHelp.IsOverrideMethod(method);

            Assert.IsTrue(result);
        }

        [TestMethod]
        public void TestReflectionHelpIsOverrideMethodNonVirtual()
        {
            var type = typeof(Derived);
            var method = type.GetMethod("DerivedMethod");
            bool result = ReflectionHelp.IsOverrideMethod(method);

            Assert.IsFalse(result);
        }

        [TestMethod]
        public void TestReflectionHelpIsOverrideMethodOverride()
        {
            var type = typeof(Derived);
            var method = type.GetMethod("VirtualOverridenMethod");
            bool result = ReflectionHelp.IsOverrideMethod(method);

            Assert.IsFalse(result);
        }

        [TestMethod]
        public void TestReflectionHelpIsOverridenMethodNonVirtual()
        {
            var type = typeof(Derived);
            var method = type.GetMethod("DerivedMethod");
            bool result = ReflectionHelp.IsOverridenMethod(method);

            Assert.IsFalse(result);
        }

        [TestMethod]
        public void TestReflectionHelpIsOverridenMethodOverriden()
        {
            var type = typeof(Derived);
            var method = type.GetMethod("VirtualOverridenMethod");
            bool result = ReflectionHelp.IsOverridenMethod(method);

            Assert.IsTrue(result);
        }

        [TestMethod]
        public void TestReflectionHelpIsOverridenMethodVirtual()
        {
            var type = typeof(Derived);
            var method = type.GetMethod("VirtualMethod");
            bool result = ReflectionHelp.IsOverridenMethod(method);

            Assert.IsFalse(result);
        }

        [TestMethod]
        public void TestReflectionHelpIsOverridenMethodNew()
        {
            var type = typeof(Derived);
            var method = type.GetMethod("NewMethod");
            bool result = ReflectionHelp.IsOverridenMethod(method);

            Assert.IsFalse(result);
        }
    }


    public class Base : DispatcherObject
    {
        public Base()
        {
        }

        public void NoParameterMethod()
        {
            throw new NotImplementedException();
        }

        public void OneParameterMethod(int param1)
        {
            throw new NotImplementedException();
        }

        public void ManyParameterMethod(int param1, string param2, ICollection<KeyValuePair<bool, long>> param3)
        {
            throw new NotImplementedException();
        }

        public virtual void OverloadMethod(bool param1)
        {
            throw new NotImplementedException();
        }

        public virtual void OverloadMethod(bool param1, string param2)
        {
            throw new NotImplementedException();
        }

        public virtual void OverloadMethod(bool param1, string param2, int param3)
        {
            throw new NotImplementedException();
        }

        public void BaseMethod()
        {
            throw new NotImplementedException();
        }

        public virtual void VirtualMethod()
        {
            throw new NotImplementedException();
        }

        [Obsolete]
        public virtual void VirtualOverridenMethod()
        {
            throw new NotImplementedException();
        }

        public void NewMethod()
        {
            throw new NotImplementedException();
        }
    }

    public class Derived : Base
    {
        public Derived()
            : base()
        {
        }

        public Derived(bool param)
            : base()
        {
        }

        public override void OverloadMethod(bool param1)
        {
            throw new NotImplementedException();
        }

        public override void OverloadMethod(bool param1, string param2)
        {
            throw new NotImplementedException();
        }

        public virtual void OverloadMethod(bool param1, int param2)
        {
            throw new NotImplementedException();
        }

        public void DerivedMethod()
        {
            throw new NotImplementedException();
        }

        [Obsolete("My obsolete")]
        public void DerivedObsoleteMethod()
        {
            throw new NotImplementedException();
        }

#pragma warning disable 0672
        public override void VirtualOverridenMethod()
        {
            throw new NotImplementedException();
        }

#pragma warning disable 0114
        public virtual void VirtualMethod()
        {
            throw new NotImplementedException();
        }

        public new void NewMethod()
        {
            throw new NotImplementedException();
        }
    }

    public class DoubleDerived : Derived
    {
        public DoubleDerived()
            : base()
        {
        }

        public override void OverloadMethod(bool param1, string param2, int param3)
        {
            throw new NotImplementedException();
        }
    }

}
